#include "UsbHostDrv.h"

/**
 * \internal
 * \brief Function called by UOTGHS interrupt to manage USB host interrupts
 *
 * USB host interrupt events are split into four sections:
 * - USB line events
 *   (VBus error, device dis/connection, SOF, reset, suspend, resume, wakeup)
 * - control endpoint events
 *   (setup reception, end of data transfer, underflow, overflow, stall, error)
 * - bulk/interrupt/isochronous endpoints events
 *   (end of data transfer, stall, error)
 */
void usb_host_interrupt(void)
{
	uint8_t pipe_int;

	// Manage SOF interrupt
	if (Is_uhd_sof()) 
	{
		uhd_sof_interrupt();
		return;
	}

	// Manage pipe interrupts
	pipe_int = uhd_get_interrupt_pipe_number();
	if (pipe_int == 0) {
		// Interrupt acked by control endpoint managed
		uhd_ctrl_interrupt();
		return;
	}
	
#ifdef SUPPORT_ACCESSORY
	if (pipe_int == g_bulkInPipe) 
	{
		Pipe_interrupt(pipe_int);
		return;
	}
	else if (pipe_int == g_bulkOutPipe)
	{
		return;
	}
#endif       
        /* // not to use any other ep, %by Santiago
	if (pipe_int != UOTGHS_EPT_NUM) {
		// Interrupt acked by bulk/interrupt/isochronous endpoint
		uhd_pipe_interrupt(pipe_int);
		return;
	}
#ifdef UHD_PIPE_DMA_SUPPORTED
	pipe_int = uhd_get_pipe_dma_interrupt_number();
	if (pipe_int != UOTGHS_EPT_NUM) {
		// Interrupt DMA acked by bulk/interrupt/isochronous endpoint
		uhd_pipe_interrupt_dma(pipe_int);
		return;
	}
#endif*/
	// USB bus reset detection
	if (Is_uhd_reset_sent()) 
        {
                //Clear reset interrupt flag
		UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSTIC; //uhd_ack_reset_sent();
		if (uhd_reset_callback != NULL) {
			uhd_reset_callback();
		}
		return;
	}

	// Manage dis/connection event
	if (Is_uhd_disconnection() && Is_uhd_disconnection_int_enabled()) {
		uhd_ack_disconnection();
		uhd_disable_disconnection_int();
		// Stop reset signal, in case of disconnection during reset
		uhd_stop_reset();
                
                //uhd_disable_reset_sent_interrupt();
                //uhd_start_reset();
                uhd_disable(false);
                ex_status.usb_role = USB_ROLE_SWITCH;
                //b_usb_switch = true;                    
                //update_jpm_status(JPM_AS_DEVICE);
                
		// Disable wakeup/resumes interrupts,
		// in case of disconnection during suspend mode
		/*UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC
				| UOTGHS_HSTIDR_RSMEDIEC
				| UOTGHS_HSTIDR_RXRSMIEC;
		uhd_sleep_mode(UHD_STATE_DISCONNECT);
		uhd_ack_connection();
		uhd_enable_connection_int();
		uhd_suspend_start = 0;
		uhd_resume_start = 0;
		uhc_notify_connection(false);*/
		return;
	} //not to care disconnect, %by Santiago
	if (Is_uhd_connection() && Is_uhd_connection_int_enabled()) {
                //Clear connection interrupt flag
		UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC; //uhd_ack_connection();                
                //disable connection intr
                UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DCONNIEC;//uhd_disable_connection_int();
		//uhd_ack_disconnection();
		//uhd_enable_disconnection_int();  //not to care disconnect, %by Santiago
		
                //Start send SOF
                //uhd_enable_sof();
                Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE);
                
                // not to use any about suspend\sleep, %by Santiago
		//uhd_sleep_mode(UHD_STATE_IDLE);
		//uhd_suspend_start = 0;
		//uhd_resume_start = 0;
		
                //uhc_notify_connection(true);
                //uhc_connection_tree(true, &g_uhc_device_root);
                uhc_enum_try = 1;
		g_uhc_device_root.conf_desc = NULL;
		g_uhc_device_root.address = 0;
		//UHC_CONNECTION_EVENT(uhc_dev_enum, true);
		uhc_enumeration_step1();
		return;
	}

        //Close all process about VBUS, %by Santiago
        /*
	// Manage Vbus error
	if (Is_uhd_vbus_error_interrupt()) {
		uhd_ack_vbus_error_interrupt();
		//UHC_VBUS_ERROR();
		return;
	}*/	
        
        //not to use sleep\wakeup, %by Santiago
        /*
	if (Is_uhd_wakeup_interrupt_enabled() && (Is_uhd_wakeup() ||
			Is_uhd_downstream_resume() || Is_uhd_upstream_resume())) {
		// Disable wakeup/resumes interrupts
		UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC
				| UOTGHS_HSTIDR_RSMEDIEC
				| UOTGHS_HSTIDR_RXRSMIEC;
		uhd_enable_sof();
		if ((!Is_uhd_downstream_resume())
				&&(!Is_uhd_disconnection())) {
			// It is a upstream resume
			// Note: When the CPU exits from a deep sleep mode, the event
			// Is_uhd_upstream_resume() can be not detected
			// because the USB clock are not available.

			// In High speed mode a downstream resume must be sent
			// after a upstream to avoid a disconnection.
			if (Is_uhd_high_speed_mode()) {
				uhd_send_resume();
			}
		}
		// Wait 50ms before restarting transfer
		uhd_resume_start = 50;
		uhd_sleep_mode(UHD_STATE_IDLE);
		return;
	}
*/
         //Close all process about VBUS, %by Santiago
        
	// Manage Vbus state change
	if (Is_otg_vbus_transition()) {
                // Check USB clock ready after asynchronous interrupt
                while (!Is_otg_clock_usable());
                //otg_unfreeze_clock();
                Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_FRZCLK);
                
		otg_ack_vbus_transition();
		return;
	}
/*
	// Other errors
	if (Is_uhd_errors_interrupt_enabled() && Is_uhd_errors_interrupt()) {
		uhd_ack_errors_interrupt();
		return;
	}
	// Still waiting VBus, ignore errors
	if (Is_uhd_vbus_enabled() && !Is_otg_vbus_high()) {
		uhd_ack_errors_interrupt();
		return;
	}*/

	//Assert(false); // Interrupt event no managed, not to use event, %by Santiago
}